<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
    <title>js call native api</title>
    <style>
        ul,li{
            list-style-type: none;
            margin:0;
            padding:0
        }
        li{
            display: block;
            padding:10px 20px;
            background:#aaa;
            color:#fff;
            border-radius: 5px;
            margin-top:20px;
            text-align: center;
        }
    </style>
</head>
<body>

<div id="temp"></div>
<div id="temp2"></div>

<ul>
    <li id="J_GotoBaidu">跳转至百度</li>
    <li id="J_NativeToJs">NativeToJs获取uid</li>
    <li id="J_HideTitle">hideTitle</li>
    <li id="J_ShowTitle">showTitle</li>
    <li id="J_PopPage">popPage1</li>
    <li id="J_OpenNewPage">openNewPage</li>
    <li id="J_PopPage2">popPage2</li>
    <li id="J_Resume">resume监听</li>
    <li id="J_Pause">pause监听</li>
    <li id="J_UA">自定义UA</li>
    <li id="J_BridgeScheme">自定义协议拦截</li>
</ul>


<script>
    var ua = navigator.userAgent;
    var IOS = 'ios';
    var ANDROID = 'android';

    /**
     * 监听浏览器回退事件
     * @param actionToDo
     */
    var pageBackFromNextPage = function(actionToDo){

        // pageshow
        // UA.android && window.addEventListener('focus', actionToDo, false);
        window.addEventListener('pageshow', function (e) {
            if (e.persisted) {
                actionToDo(e);
            }
        }, false);

        // visibilityChange
        document.addEventListener('visibilitychange', function (e) {
            if (document.visibilityState == 'visible' || !document.hidden) {
                actionToDo(e);
            }
        }, false);

        // webkitVisibilityChange
        document.addEventListener('webkitVisibilitychange', function (e) {
            if (document.webkitVisibilityState == 'visible' || !document.webkitHidden) {
                actionToDo(e);
            }
        }, false);
    };


    /**
     * 监听浏览器暂停事件（压入后台）
     * @param actionToDo
     */
    var pagePause = function(actionToDo){

        // pageshow
        // UA.android && window.addEventListener('focus', actionToDo, false);
        window.addEventListener('pagehide', function (e) {
            if (e.persisted) {
                actionToDo(e);
            }
        }, false);

        // visibilityChange
        document.addEventListener('visibilitychange', function (e) {
            if (document.visibilityState == 'hidden' || document.hidden) {
                actionToDo(e);
            }
        }, false);

        // webkitVisibilityChange
        document.addEventListener('webkitVisibilitychange', function (e) {
            if (document.webkitVisibilityState == 'hidden' || document.webkitHidden) {
                actionToDo(e);
            }
        }, false);
    };

    function getDeviceInfo(){ //获取设备信息
        var device = {
            type: null,
            version: null
        };
        //设备类型
        if (/\(i[^;]+;( U;)? CPU.+Mac OS X/.test(ua)) {
            // iOS: Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H321 AliApp(LX/5.8.1) AliTrip/5.8.1
            device.type = IOS;

            // iOS 版本号提取
            var iosVersion = /\b[0-9]+_[0-9]+(?:_[0-9]+)?\b/.exec(ua);
            if (iosVersion && iosVersion[0]) {
                device.version = iosVersion[0].replace(/_/g, '.');
            }
        } else if (/Android/i.test(ua)) {
            device.type = ANDROID;
            var match = ua.match(/Android\s+([\d\.]+)/i);
            device.version = match && match[1];
        } else {
            device.type = undefined;
        }
        return device;
    }

    var isJSBridgeAPPDemo = function(){
        if(/JSBridgeDemoUserAgent/.test(ua)){
            return true;
        }
        return false;
    };

    var JSBridge = {
        isJSBridgeAPPDemo: isJSBridgeAPPDemo(),
        device: getDeviceInfo(),
        eventMap: {
            //事件队列
        },
        uid: 0,
        deviceRouter: function(method, params, callback, isHold){
            if(!this.isJSBridgeAPPDemo){ return console.log("isJSBridgeAPPDemo：false"); }

            if(this.device.type == IOS){
                this.iosMethod(method, params, callback, isHold);
            } else if (this.device.type == ANDROID){
                this.androidMethod(method, params, callback, isHold);
            } else {
                console.error("请在native端使用此方法：" + method);
            }
        },
        iosMethod: function(method, params, callback, isHold){ //ios通用方法
            var self = this;
            var uid = this.uid;

            if(callback){
                this.eventMap[method + uid] = function(data){
                    callback && callback(data);
                    if(!isHold){
                        delete self.eventMap[method + uid];
                    }
                };
                this.uid = uid + 1;
            }

            try{
                var msgObj = {
                    nativeMethod: method
                };
                if(callback){
                    msgObj.callback = method + uid;
                }
                if(params){
                    msgObj.params = JSON.stringify(params);
                }

                window.webkit.messageHandlers.JSBridge.postMessage(msgObj);
            }catch(e){
                console.error(JSON.stringify(e));
                console.error("需要在ios设备内使用WKWebView");
            }

        },
        androidMethod: function(method, params, callback, isHold){ //android通用方法

            var self = this;
            var uid = this.uid;

            if(callback){
                this.eventMap[method + uid] = function(data){
                    callback && callback(data);
                    if(!isHold){
                        delete self.eventMap[method + uid];
                    }
                };
                this.uid = uid + 1;
            }

            try{

                if(params && callback){
                    JSBridgeAndroid[method](JSON.stringify(params), method + uid);
                } else if(params) {
                    JSBridgeAndroid[method](JSON.stringify(params));
                } else if(callback) {
                    JSBridgeAndroid[method](method + uid);
                } else {
                    JSBridgeAndroid[method]();
                }

            }catch(e){
                console.error(JSON.stringify(e));
                console.error("需要在android设备内使用JSBridge功能，无全局对象JSBridgeAndroid");
            }

        },
        getDeviceId: function(callback){ //获取设备id

            this.deviceRouter("getDeviceId", null, callback);

        },

        openPage: function(url){ //打开新的webview

            this.deviceRouter("openPage", {url: url}, null);
            if(!this.isJSBridgeAPPDemo){
                location.href = url;
            }
        },

        popPage: function(n){ //关闭页面

            if(!n) { n = 1 }
            this.deviceRouter("popPage", {step: n}, null);

            if(!this.isJSBridgeAPPDemo){
                if(n == 1){
                    history.back();
                } else {
                    history.go(-n);
                }
            }
            // JSBridgeAndroid.popPage(n);
        },

        hideTitle: function(){ //隐藏native title bar

            this.deviceRouter("hideTitle", null, null);

            // JSBridgeAndroid.hideTitle();
        },

        showTitle: function(){ //显示native title bar

            this.deviceRouter("showTitle", null, null);

            // JSBridgeAndroid.showTitle();
        },

        addResumeEvent: function(callback){ //resume

            this.deviceRouter("addResumeEvent", null, callback, true);

            if(!this.isJSBridgeAPPDemo){
                pageBackFromNextPage(callback);
            }

            // JSBridgeAndroid.addResumeEvent(name + uid);

        },

        addPauseEvent: function(callback){ //pause

            this.deviceRouter("addPauseEvent", null, callback, true);

            if(!this.isJSBridgeAPPDemo){
                pagePause(callback);
            }
        }

    };

    var J_GotoBaidu = document.getElementById("J_GotoBaidu");
    J_GotoBaidu.onclick = function(){
        JSBridge.openPage("https://www.baidu.com");
    };

    var J_NativeToJs = document.getElementById("J_NativeToJs");
    J_NativeToJs.onclick = function(){
        JSBridge.getDeviceId(function(data){
            document.getElementById('temp').innerHTML = data;
        });
    };

    var J_HideTitle = document.getElementById("J_HideTitle");
    J_HideTitle.onclick = function(){
        JSBridge.hideTitle();
    };
    var J_ShowTitle = document.getElementById("J_ShowTitle");
    J_ShowTitle.onclick = function(){
        JSBridge.showTitle();
    };
    var J_PopPage = document.getElementById("J_PopPage");
    J_PopPage.onclick = function(){
        JSBridge.popPage();
    };
    var J_OpenNewPage = document.getElementById("J_OpenNewPage");
    J_OpenNewPage.onclick = function(){
        JSBridge.openPage();
    };
    var J_PopPage2 = document.getElementById("J_PopPage2");
    J_PopPage2.onclick = function(){
        JSBridge.popPage(2);
    };


    var J_Resume = document.getElementById("J_Resume");
    J_Resume.onclick = function(){
        JSBridge.addResumeEvent(function(){
             document.getElementById('temp').innerHTML = "app 被压入前台";
         });
    };

    var J_Pause = document.getElementById("J_Pause");
    J_Pause.onclick = function(){
        JSBridge.addPauseEvent(function(){
            document.getElementById('temp2').innerHTML = "app 被压入后台";

        });
    };

    var J_UA = document.getElementById("J_UA");
    J_UA.onclick = function(){
        alert(navigator.userAgent);
    };

    var J_BridgeScheme = document.getElementById("J_BridgeScheme");
    J_BridgeScheme.onclick = function(){
        //ios接收到的scheme的值 始终为小写
        var body = document.getElementsByTagName("body")[0];
        var iframe = document.createElement('iframe');
        iframe.src = "jsbridge://openPage?url=" + encodeURIComponent("https://www.baidu.com");
        body.appendChild(iframe);
        // location.href = "jsbridge://openPage?url=" + encodeURIComponent("https://www.baidu.com");
    };

</script>

</body>
</html>